package com.cly.handler;

import com.cly.base.contants.CacheKeysConstants;
import com.cly.base.contants.SocketConstants;
import com.cly.utils.RedisClientsUtils;
import com.cly.utils.TokenUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;

import java.util.Map;

/**
 * Websocket拦截器
 *
 * @author by 春风能解释
 * <p>
 * 2025/2/14
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class AuthHandshakeInterceptor extends HttpSessionHandshakeInterceptor {

    /**
     * redis客户端工具
     */
    private final RedisClientsUtils redisClientsUtils;

    /**
     * 握手前，进行用户身份校验识别,  继续握手返回true, 中断握手返回false. 通过attributes参数设置登录的用户信息
     *
     * @param request     请求
     * @param response    响应
     * @param wsHandler   处理器
     * @param attributes: 即对应的是Message中的 simpSessionAttributes 请求头
     * @return 继续握手返回true, 中断握手返回false
     */
    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) {
        HttpHeaders headers = request.getHeaders();
        String token = headers.getFirst(SocketConstants.SEC_WEBSOCKET_PROTOCOL);
        // 判断token是否为空
        if (!StringUtils.hasText(token)) {
            return false;
        }
        // 获取用户id
        Long userId = TokenUtils.checkToken(token, Long.class);
        // 判断token是否一致
        String cacheToken = redisClientsUtils.get(CacheKeysConstants.UserKeys.USER_TOKEN + userId);
        // token不一致
        if (!token.equals(cacheToken)) {
            return false;
        }
        response.getHeaders().add(SocketConstants.SEC_WEBSOCKET_PROTOCOL, token);
        return true;
    }

    /**
     * 成功建立连接后
     *
     * @param request   请求
     * @param response  响应
     * @param wsHandler 处理器
     * @param ex        异常
     */
    @Override
    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception ex) {
        log.info("websocket连接建立成功!");
        super.afterHandshake(request, response, wsHandler, ex);
    }
}
